package ael.imarkket.Library;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.util.ArrayList;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;

import ael.imarkket.R;
import android.content.Context;

public class HttpPostGet {

	public enum RequestMethod {
		GET, POST
	}

	private ArrayList<NameValuePair>	params;
	private ArrayList<NameValuePair>	headers;

	private String						url;
	private int							id_app;

	private int							responseCode;
	private String						message;

	private String						response;

	private String						codificacion;

	public String getCodificacion() {
		return codificacion;
	}

	public String getResponse() {
		return response;
	}

	public String getErrorMessage() {
		return message;
	}

	public int getResponseCode() {
		return responseCode;
	}

	public HttpPostGet(String url, String iso_utf, int ID_APP) {
		this.url = url;
		params = new ArrayList<NameValuePair>();
		headers = new ArrayList<NameValuePair>();
		codificacion = iso_utf;
		id_app = ID_APP;
	}

	public void AddParam(String name, String value) {
		params.add(new BasicNameValuePair(name, value));
	}

	public void AddHeader(String name, String value) {
		headers.add(new BasicNameValuePair(name, value));
	}

	public void Execute(RequestMethod method, String pHTTP_USER_AGENT_APP_ANDROID, ArrayList<NameValuePair> ArrayOperation, Context ctx, String Operation)
			throws SocketTimeoutException, ClientProtocolException, IOException {

		// A�adimos los parametros que decidir� que hace la aplicacion web
		App_To_Http_OperationAddParameter(ArrayOperation, ctx, Operation);

		switch (method) {
			case GET: {
				// add parameters
				String combinedParams = "";
				if (!params.isEmpty()) {
					combinedParams += "?";
					for (NameValuePair p : params) {
						String paramString;
						paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(), this.getCodificacion());
						if (combinedParams.length() > 1) {
							combinedParams += "&" + paramString;
						} else {
							combinedParams += paramString;
						}

					}
				}

				HttpGet request = new HttpGet(url + combinedParams);

				// add headers
				for (NameValuePair h : headers) {
					request.addHeader(h.getName(), h.getValue());
				}

				// Personalizamos el header HTTP_USER_AGENT
				request.setHeader(ctx.getString(R.string.HTTP_USER_AGENT), pHTTP_USER_AGENT_APP_ANDROID);

				executeRequest(request);
				break;
			}
			case POST: {
				HttpPost request = new HttpPost(url);

				// add headers
				for (NameValuePair h : headers) {
					request.addHeader(h.getName(), h.getValue());
				}

				if (!params.isEmpty()) {
					request.setEntity(new UrlEncodedFormEntity(params, this.getCodificacion()));
				}

				// Personalizamos el header HTTP_USER_AGENT
				request.setHeader(ctx.getString(R.string.HTTP_USER_AGENT), pHTTP_USER_AGENT_APP_ANDROID);

				executeRequest(request);
				break;
			}
		}
	}

	private void executeRequest(HttpUriRequest request) throws ClientProtocolException, SocketTimeoutException, IOException {

		// Para el timeout
		HttpParams TimeOut = new BasicHttpParams();
		HttpConnectionParams.setConnectionTimeout(TimeOut, 5000);
		HttpConnectionParams.setSoTimeout(TimeOut, 10000);

		HttpClient client = new DefaultHttpClient(TimeOut);
		HttpResponse httpResponse;
		httpResponse = client.execute(request);
		responseCode = httpResponse.getStatusLine().getStatusCode();
		message = httpResponse.getStatusLine().getReasonPhrase();

		HttpEntity entity = httpResponse.getEntity();

		if (entity != null) {

			InputStream instream = entity.getContent();
			response = convertStreamToString(instream);

			// Closing the input stream will trigger connection release
			instream.close();
		}
	}

	private static String convertStreamToString(InputStream is) {

		BufferedReader reader = new BufferedReader(new InputStreamReader(is));
		StringBuilder sb = new StringBuilder();

		String line = null;
		try {
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				is.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return sb.toString();
	}

	public void App_To_Http_OperationAddParameter(ArrayList<NameValuePair> ArrayOperation, Context ctx, String Operation) {
		// Los parametros los a�ado de forma inversa para que en el log se vean
		// correctamente

		// Inicializamos la ApiCripter
		ApiCrypter AC = new ApiCrypter();

		// json con la descripcion del dispositivo
		try {
			this.AddParam(ctx.getString(R.string.STR_JSON_OPERATION),
					ApiCrypter.bytesToHex(AC.encrypt(ApiJSON.getInstance(ctx).createJSON(ArrayOperation, ctx, id_app).toString())));
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// par�metro que indica lo que voy a hacer
		this.AddParam(ctx.getString(R.string.STR_FORM_OPERATION), Operation);
		// Siempre se pasan 3 parámetros al fichero php
		// 1 -> json_operation = { } que el el json entero con las descripciones
		// 2 -> form_operation = APP_LOGIN, APP_CLOSE, que indica lo que voy a
		// hacer Básicamente es para que el php sepa lo que hacer
		// 3 -> Este tercer parámetro se inserta automaticamente en el php y no
		// se envía. Determina si es una aplicación web, móvil o similar, esto
		// no lo hace la app sino que se "advina" en tiempo de ejecución.
		// Es posible que sea bueno pasarlo y no dejar a php que lo adivine.
	}
}